package com.demon.androidbasic.base

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.demon.net.*
import com.demon.net.handler.DefaultResponseResultHandler
import com.demon.net.handler.IResponseResultHandler
import com.demon.net.handler.IResponseResultHandlerCreator
import com.demon.net.ui.UIState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

/**
 * ViewModel 基类
 * <p/>
 *
 * 封装App内ViewModel公用的方法
 *
 * @author zhaozeyang
 * @date 2020/10/15
 */
open class BaseViewModel : ViewModel(), IRemoteServiceInvoke, IResponseResultHandlerCreator {

    protected val mExecutor by lazy { createNetExecutor() }

    val uiStateLiveData = MutableLiveData<UIState>()

    val mResponseResultHandler by lazy { createResponseResultHandler() }

    override fun createNetExecutor(): IExecutor = AppResponseExecutor()

    override fun <T : Any> rpcExecute(
        rpcCall: suspend () -> IAppResponse<T>,
        uiState: MutableLiveData<UIState>,
        responseResultHandler: IResponseResultHandler?,
        success: ((t: T?) -> Unit)?,
    ) {
        executeDefault {
            val result = mExecutor.executeRequest(call = {
                rpcCall.invoke()
            })
            if (result is ResponseResult.Success) {
                success?.invoke(result.data)
            } else {
                responseResultHandler?.handle(uiState, result)
            }
        }
    }

    override fun createResponseResultHandler() = DefaultResponseResultHandler()

    /**
     * 默认调度器执行
     */
    fun executeDefault(func: suspend () -> Unit) {
        viewModelScope.launch {
            func.invoke()
        }
    }

    /**
     * 子线程调用，主线程回调
     */
    fun executeIO(func: suspend () -> Unit, callback: (() -> Unit)? = null) {
        viewModelScope.launch(Dispatchers.IO) {
            func.invoke()
            callback?.let {
                viewModelScope.launch(Dispatchers.Main) {
                    it.invoke()
                }
            }
        }
    }

}